﻿//using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Net.Mail;
using System.Web.Caching;

public class App_Email_Info : Standard_Info
{

    public const string CS_STATUS_CREATED = "CREATED";

    public const string CS_STATUS_WAITING = "WAITING";
    public const string CS_STATUS_SENT = "SENT";

    public const string CS_STATUS_FAILED = "FAILED";
    public App_Email_Info()
    {
        _Email_Status = CS_STATUS_CREATED;
        _Create_Date = DateTime.Now;
        _Create_By = "SYSTEM";
    }

    public App_Email_Info(string _to, string _cc, string _subject, string _body)
    {
        _Send_To = _to;
        _Send_CC = _cc;
        _Email_Subject = _subject;
        _Email_Body = _body;
        _Email_Status = CS_STATUS_CREATED;
        _Create_Date = DateTime.Now;
        _Create_By = "SYSTEM";
    }

    private Int32 _Email_ID;
    public Int32 Email_ID
    {
        get { return _Email_ID; }
        set { _Email_ID = value; }
    }

    private string _Send_To;
    public string Send_To
    {
        get { return _Send_To; }
        set { _Send_To = value; }
    }

    private string _Send_CC;
    public string Send_CC
    {
        get { return _Send_CC; }
        set { _Send_CC = value; }
    }

    private string _Email_Subject;
    public string Email_Subject
    {
        get { return _Email_Subject; }
        set { _Email_Subject = value; }
    }

    private string _Email_Body;
    public string Email_Body
    {
        get { return _Email_Body; }
        set { _Email_Body = value; }
    }

    private DateTime _Create_Date;
    public DateTime Create_Date
    {
        get { return _Create_Date; }
        set { _Create_Date = value; }
    }

    private string _Create_By;
    public string Create_By
    {
        get { return _Create_By; }
        set { _Create_By = value; }
    }

    private DateTime _Send_Date;
    public DateTime Send_Date
    {
        get { return _Send_Date; }
        set { _Send_Date = value; }
    }

    private string _Send_Err;
    public string Email_Desc
    {
        get { return _Send_Err; }
        set { _Send_Err = value; }
    }

    private string _Email_Status;
    public string Email_Status
    {
        get { return _Email_Status; }
        set { _Email_Status = value; }
    }
}

public class App_Email_Config : Standard_Info
{

    private string _Server_Name;
    public string Server_Name
    {
        get { return _Server_Name; }
        set { _Server_Name = value; }
    }

    private short _Server_Port;
    public short SMTP_Port
    {
        get { return _Server_Port; }
        set { _Server_Port = value; }
    }

    private short _Pop_Port;
    public short POP_Port
    {
        get { return _Pop_Port; }
        set { _Pop_Port = value; }
    }

    private string _User_Name;
    public string User_Name
    {
        get { return _User_Name; }
        set { _User_Name = value; }
    }

    private string _User_Password;
    public string User_Password
    {
        get { return _User_Password; }
        set { _User_Password = value; }
    }

    private bool _Use_SSL;
    public bool Use_SSL
    {
        get { return _Use_SSL; }
        set { _Use_SSL = value; }
    }

    private bool _Delete_Sent;
    public bool Delete_Sent
    {
        get { return _Delete_Sent; }
        set { _Delete_Sent = value; }
    }

    public string From_Address
    {
        get
        {
            if (_User_Name.Contains("@"))
            {
                return _User_Name;
            }
            else
            {
                if (_Server_Name.StartsWith("smtp."))
                {
                    return _User_Name + "@" + _Server_Name.Substring("smtp.".Length);
                }
                else if (_Server_Name.StartsWith("mail."))
                {
                    return _User_Name + "@" + _Server_Name.Substring("mail.".Length);
                }
                else
                {
                    return _User_Name + "@" + _Server_Name;
                }
            }
        }
    }

    private string _Display_Name;
    public string Display_Name
    {
        get { return _Display_Name; }
        set { _Display_Name = value; }
    }

    private short _Send_Amount;
    public short Send_Amount
    {
        get
        {
            if (_Send_Amount <= 0)
                _Send_Amount = 10;
            return _Send_Amount;
        }
        set { _Send_Amount = value; }
    }
}

public class App_Email_Controller
{

    #region "Contructor"
    private static App_Email_Controller _instance;
    protected App_Email_Controller()
    {
    }
    protected void Dispose()
    {
        _instance = null;
    }
    private static object _syncLock = new object();
    public static new App_Email_Controller Instance()
    {
        if (_instance == null)
        {
            lock (_syncLock)
            {
                if (_instance == null)
                {
                    _instance = new App_Email_Controller();
                }
            }
        }
        return _instance;
    }
    #endregion


    private App_Email_Config _emailConfig;
    private void InitConfig()
    {
        //get config info
        if (_emailConfig == null)
        {
            _emailConfig = GetConfig();
        }
    }

    public void SendAll()
    {
        try
        {
            //Init confid
            InitConfig();
            //
            List<App_Email_Info> lstEmail = default(List<App_Email_Info>);
            //Send new email first
            lstEmail = List(App_Email_Info.CS_STATUS_CREATED, _emailConfig.Send_Amount);
            if (lstEmail != null)
            {
                foreach (App_Email_Info objInfo in lstEmail)
                {
                    Send(objInfo);
                    System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
                    //sleep 5 sec
                }
            }
            //Resend waiting email
            lstEmail = List(App_Email_Info.CS_STATUS_WAITING, _emailConfig.Send_Amount);
            if (lstEmail != null)
            {
                foreach (App_Email_Info objInfo in lstEmail)
                {
                    Send(objInfo);
                    System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
                    //sleep 5 sec
                }
            }
        }
        catch (Exception ex)
        {
            //Do nothing
            throw ex;
        }
    }

    internal void Send(App_Email_Info objInfo)
    {
        try
        {
            SmtpClient smtpClient = new SmtpClient();
            //init client
            smtpClient.UseDefaultCredentials = false;
            smtpClient.Credentials = new System.Net.NetworkCredential(_emailConfig.User_Name, _emailConfig.User_Password);
            smtpClient.Host = _emailConfig.Server_Name;
            smtpClient.Port = _emailConfig.SMTP_Port;
            smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
            smtpClient.EnableSsl = _emailConfig.Use_SSL;
            //init message
            MailMessage message = new MailMessage();
            message.From = new MailAddress(_emailConfig.From_Address, _emailConfig.Display_Name, System.Text.Encoding.UTF8);
            objInfo.Send_To = objInfo.Send_To.Replace(",", ";");
            foreach (string sTo in objInfo.Send_To.Split(new char[]{';'}))
            {
                //message.[To].Add(sTo.Trim)
                message.To.Add(MailAddress_Parse(sTo.Trim()));
            }
            //
            if (!string.IsNullOrEmpty(objInfo.Send_CC))
            {
                objInfo.Send_CC = objInfo.Send_CC.Replace(",", ";");
                foreach (string sCC in objInfo.Send_CC.Split(new char[]{';'}))
                {
                    //message.CC.Add(sCC.Trim)
                    message.CC.Add(MailAddress_Parse(sCC.Trim()));
                }
            }
            message.Subject = objInfo.Email_Subject;
            message.Body = objInfo.Email_Body;
            message.IsBodyHtml = true;
            message.BodyEncoding = System.Text.Encoding.UTF8;
            //send message
            smtpClient.Send(message);
            //
            objInfo.Email_Desc = "";
            objInfo.Email_Status = App_Email_Info.CS_STATUS_SENT;
        }
        catch (Exception ex)
        {
            objInfo.Email_Desc = ex.Message;
            if ((ex.InnerException != null))
            {
                objInfo.Email_Desc += " | " + ex.InnerException.Message;
            }
            objInfo.Email_Status = App_Email_Info.CS_STATUS_WAITING;
        }
        //delete sent email
        if (_emailConfig.Delete_Sent && objInfo.Email_Status == App_Email_Info.CS_STATUS_SENT)
        {
            Delete(objInfo.Email_ID);
            return;
        }
        //update status
        objInfo.Send_Date = DateTime.Now;
        UpdateStatus(objInfo);
    }

    private MailAddress MailAddress_Parse(string sAddress)
    {
        if (sAddress.Contains("<"))
        {
            string sEmail = null;
            string sDisplay = null;
            sDisplay = sAddress.Substring(0, sAddress.IndexOf("<") - 1);
            sEmail = sAddress.Substring(sAddress.IndexOf("<") + 1);
            sEmail = sEmail.Substring(0, sEmail.Length - 1);
            return new MailAddress(sEmail, sDisplay);
        }
        else
        {
            return new MailAddress(sAddress);
        }
    }

    public void SetConfig(App_Email_Config objConfig)
    {
        if (!Globals.String_IsBase64(objConfig.User_Password))
            objConfig.User_Password = Globals.String_Encrypt(objConfig.User_Password, EncryptKey(objConfig));
        //
        SystemController.Instance().SysParam_Update("EMAIL_SERVER_NAME", objConfig.Server_Name);
        SystemController.Instance().SysParam_Update("EMAIL_SMTP_PORT", Globals.Object_GetValue<string>(objConfig.SMTP_Port));
        SystemController.Instance().SysParam_Update("EMAIL_POP_PORT", Globals.Object_GetValue<string>(objConfig.POP_Port));
        SystemController.Instance().SysParam_Update("EMAIL_USER_NAME", objConfig.User_Name);
        SystemController.Instance().SysParam_Update("EMAIL_USER_PASSWORD", objConfig.User_Password);
        SystemController.Instance().SysParam_Update("EMAIL_USE_SSL", Globals.Object_GetValue<string>(objConfig.Use_SSL));
        SystemController.Instance().SysParam_Update("EMAIL_DELETE_SENT", Globals.Object_GetValue<string>(objConfig.Delete_Sent));
        SystemController.Instance().SysParam_Update("EMAIL_DISPLAY_NAME", objConfig.Display_Name);
        SystemController.Instance().SysParam_Update("EMAIL_SEND_AMOUNT", Globals.Object_GetValue<string>(objConfig.Send_Amount));
        //
        _emailConfig = objConfig;
        if (Globals.String_IsBase64(objConfig.User_Password))
            _emailConfig.User_Password = Globals.String_Decrypt(_emailConfig.User_Password, EncryptKey(_emailConfig));
    }

    private string EncryptKey(App_Email_Config objConfig)
    {
        return objConfig.User_Name + objConfig.Server_Name;
    }

    public App_Email_Config GetConfig()
    {
        App_Email_Config objConfig = new App_Email_Config();
        DataRowEx paramEx = SystemController.Instance().SysParam_SelectGroup("EMAIL");
        objConfig.Server_Name = Globals.Object_GetValue<string>(paramEx.Item("EMAIL_SERVER_NAME"));
        objConfig.SMTP_Port = Globals.Object_GetValue<short>(paramEx.Item("EMAIL_SMTP_PORT"));
        objConfig.POP_Port = Globals.Object_GetValue<short>(paramEx.Item("EMAIL_POP_PORT"));
        objConfig.User_Name = Globals.Object_GetValue<string>(paramEx.Item("EMAIL_USER_NAME"));
        objConfig.User_Password = Globals.Object_GetValue<string>(paramEx.Item("EMAIL_USER_PASSWORD"));
        objConfig.Use_SSL = Globals.Object_GetValue<bool>(paramEx.Item("EMAIL_USE_SSL"));
        objConfig.Delete_Sent = Globals.Object_GetValue<bool>(paramEx.Item("EMAIL_DELETE_SENT"));
        objConfig.Send_Amount = Globals.Object_GetValue<short>(paramEx.Item("EMAIL_SEND_AMOUNT"));
        objConfig.Display_Name = Globals.Object_GetValue<string>(paramEx.Item("EMAIL_DISPLAY_NAME"));
        //
        if (Globals.String_IsBase64(objConfig.User_Password))
        {
            objConfig.User_Password = Globals.String_Decrypt(objConfig.User_Password, EncryptKey(objConfig));
        }
        else
        {
            SystemController.Instance().SysParam_Update("EMAIL_USER_PASSWORD", Globals.String_Encrypt(objConfig.User_Password, EncryptKey(objConfig)));
        }
        //
        return objConfig;
    }

    //------------------------------
    public DataTable Browse(string sStatus, int iPageSize, int iPageIndex, ref int iTotal)
    {
        DataSet ds = DataConnect.ExecuteDataset(DataConnect.WorkingConnect, "App_Email_Browse", sStatus, iPageSize, iPageIndex);
        return Globals.DataPager(ds, ref iTotal);
    }

    public void Insert(App_Email_Info objInfo)
    {
        objInfo.Email_ID = Globals.Object_GetValue<int>(DataConnect.ExecuteScalar(DataConnect.WorkingConnect, "App_Email_Insert", Globals.DB_GetNull(objInfo.Send_To), Globals.DB_GetNull(objInfo.Send_CC), Globals.DB_GetNull(objInfo.Email_Subject), Globals.DB_GetNull(objInfo.Email_Body), Globals.DB_GetNull(objInfo.Create_Date), Globals.DB_GetNull(objInfo.Create_By), Globals.DB_GetNull(objInfo.Email_Desc), Globals.DB_GetNull(objInfo.Email_Status)));
    }

    public void UpdateStatus(App_Email_Info objInfo)
    {
        DataConnect.ExecuteNonQuery(DataConnect.WorkingConnect, "App_Email_UpdateStatus", objInfo.Email_ID, Globals.DB_GetNull(objInfo.Send_Date), Globals.DB_GetNull(objInfo.Email_Desc), Globals.DB_GetNull(objInfo.Email_Status));
    }

    public void Delete(Int32 iEmail_ID)
    {
        DataConnect.ExecuteNonQuery(DataConnect.WorkingConnect, "App_Email_Delete", iEmail_ID);
    }

    public DataRowEx SelectRow(Int32 iEmail_ID)
    {
        return DataConnect.ExecuteRow(DataConnect.WorkingConnect, "App_Email_SelectByID", iEmail_ID);
    }

    public App_Email_Info SelectByID(Int32 iEmail_ID)
    {
        //DataRowEx drEx = DataConnect.ExecuteRow(DataConnect.WorkingConnect, "App_Email_SelectByID", iEmail_ID);
        //App_Email_Info info = new App_Email_Info();
        //return CBO.FillObject(drEx, info.GetType());
        return null;
    }

    public List<App_Email_Info> List(string sStatus, Int16 iCount)
    {
        return Globals.DataTable_FillList<App_Email_Info>(DataConnect.ExecuteTable(DataConnect.WorkingConnect, "App_Email_List", sStatus, iCount));
    }
}
